package cn.moukou.dictator.service.node;

import cn.moukou.dictator.dao.node.KVNodeDAO;
import cn.moukou.dictator.dao.relation.KVNODE_RELATION_DAO;
import cn.moukou.dictator.pojo.*;
import cn.moukou.dictator.pojo.node.KVNode;
import cn.moukou.dictator.util.Resp;
import cn.moukou.dictator.util.VOUtil;
import cn.moukou.dictator.vo.NodeVO;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class NodeService {
    @Autowired
    KVNodeDAO nodeDAO;
    @Autowired
    KVNODE_RELATION_DAO relationDao;

    private List<NodeVO> vo(List<KVNode> list) {
        List<NodeVO> resList = new ArrayList<>();
        for(KVNode kvNode : list) {
            resList.add(new NodeVO((kvNode)));
        }
        return resList;
    }

    public Map<String, Object> getAllNodeInPage(Integer page, Integer pageSize) {
        List<KVNode> tmpList = nodeDAO.customFindAllOrderByType();
        List<NodeVO> voList = VOUtil.getNodeVOList(tmpList);
        return sliceListByPage(voList, page, pageSize);
    }

    public Map<String, Object> getAllNodeInMap() {
        Map<String, Object> res = new HashMap<>();
        res.put("activity", vo(nodeDAO.findByNodeType("activity")));
        res.put("award", vo(nodeDAO.findByNodeType("award")));
        res.put("class_room", vo(nodeDAO.findByNodeType("class_room")));
        res.put("competition", vo(nodeDAO.findByNodeType("competition")));
        res.put("student", vo(nodeDAO.findByNodeType("student")));
        res.put("student_organization", vo(nodeDAO.findByNodeType("student_organization")));
        res.put("teacher", vo(nodeDAO.findByNodeType("teacher")));
        return res;
    }

    public Map<String, Object> getNodeByType(String type, Integer page, Integer pageSize) {
        List<KVNode> tmpList = nodeDAO.findByNodeType(type);
        List<NodeVO> voList = VOUtil.getNodeVOList(tmpList);
        return sliceListByPage(voList, page, pageSize);
    }


    public NodeVO addNode(Map<String, Object> params) {
        String nodeType = (String) params.get("nodeType");
        KVNode kvNode = new KVNode();
        kvNode.setNodeType(nodeType);
        kvNode = setKVNodeByNodeType(kvNode, nodeType, params);
        return new NodeVO(nodeDAO.save(kvNode));
    }

    public void deleteNode(Long id) {
        nodeDAO.deleteById(id);
    }

    public boolean updateNode(Map<String, Object> params) {
        Long id = new Long ((Integer) params.get("id"));
        KVNode kvNode = nodeDAO.findById(id).orElse(null);
        if(kvNode==null) {
            return false;
        }
        String nodeType = kvNode.getNodeType();
        if(!nodeType.equals((String) params.get("nodeType"))) {
            return false;
        }
        kvNode = setKVNodeByNodeType(kvNode, nodeType, params);
        nodeDAO.save(kvNode);
        return true;
    }

    private KVNode setKVNodeByNodeType(KVNode kvNode, String nodeType, Map<String, Object> params) {
        switch (nodeType) {
            case "activity":
                Activity activity = JSONObject.parseObject(JSONObject.toJSONString(params), Activity.class);
                kvNode.setActivity(activity);
                break;
            case "award":
                Award award = JSONObject.parseObject(JSONObject.toJSONString(params), Award.class);
                kvNode.setAward(award);
                break;
            case "class_room":
                ClassRoom classRoom = JSONObject.parseObject(JSONObject.toJSONString(params), ClassRoom.class);
                kvNode.setClassRoom(classRoom);
                break;
            case "competition":
                Competition competition = JSONObject.parseObject(JSONObject.toJSONString(params), Competition.class);
                kvNode.setCompetition(competition);
                break;
            case "student":
                Student student = JSONObject.parseObject(JSONObject.toJSONString(params), Student.class);
                kvNode.setStudent(student);
                break;
            case "student_organization":
                StudentOrganization studentOrganization = JSONObject.parseObject(JSONObject.toJSONString(params), StudentOrganization.class);
                kvNode.setStudentOrganization(studentOrganization);
                break;
            case "teacher":
                Teacher teacher = JSONObject.parseObject(JSONObject.toJSONString(params), Teacher.class);
                kvNode.setTeacher(teacher);
                break;
            default:
                return null;
        }
        return kvNode;
    }

    private Map<String, Object> sliceListByPage(List<NodeVO> voList, Integer page, Integer pageSize) {
        Map<String, Object> map = new HashMap<>();
        int total = voList.size();
        int lo = (page-1) * pageSize;
        int hi = page * pageSize;
        if(hi > total) {
            hi = total;
        }
        if(lo<hi) {
            map.put("nodeList", voList.subList(lo, hi));
        } else {
            map.put("nodeList", new ArrayList<>());
        }
        map.put("total", total);
        return map;
    }

    public Map<String, Object> getOneNode(Integer id) {
        Map<String, Object> res = new HashMap<>();
        KVNode kvNode = nodeDAO.findById(new Long(id)).orElse(null);
        if(kvNode!=null) {
            NodeVO nodeVO = new NodeVO(kvNode);
            res.put("node", nodeVO);
            res.put("relationList", VOUtil.getRelationVOList(relationDao.customFindByStartId(nodeVO.getId())));
        } else {
            res.put("node", null);
            res.put("relationList", null);
        }
        return res;
    }
}
